package com.htstar.ovms.enterprise.service.impl;

import cn.afterturn.easypoi.cache.manager.IFileLoader;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.htstar.ovms.admin.api.feign.EtpInfoFeign;
import com.htstar.ovms.admin.api.vo.EtpInfoSVo;
import com.htstar.ovms.common.core.i18n.MsgCode;
import com.htstar.ovms.common.core.util.R;
import com.htstar.ovms.common.security.service.OvmsUser;
import com.htstar.ovms.common.security.util.SecurityUtils;
import com.htstar.ovms.device.api.vo.DeviceImportVO;
import com.htstar.ovms.device.api.vo.ImportVO;
import com.htstar.ovms.enterprise.api.constant.CardCostInfoConstant;
import com.htstar.ovms.enterprise.api.entity.CarEtcCard;
import com.htstar.ovms.enterprise.api.entity.CarInfo;
import com.htstar.ovms.enterprise.api.entity.CardCostInfo;
import com.htstar.ovms.enterprise.api.req.CarFileManageReq;
import com.htstar.ovms.enterprise.api.vo.EtcCardPageVO;
import com.htstar.ovms.enterprise.mapper.CarEtcCardMapper;
import com.htstar.ovms.enterprise.service.CarEtcCardService;
import com.htstar.ovms.enterprise.service.CarInfoService;
import com.htstar.ovms.enterprise.service.CardCostInfoService;
import com.htstar.ovms.enterprise.api.req.RechargeReq;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

import static cn.hutool.core.util.NumberUtil.roundStr;

/**
 * etc卡
 *
 * @author lw
 * @date 2020-06-23 13:54:59
 */
@Service
@Slf4j
public class CarEtcCardServiceImpl extends ServiceImpl<CarEtcCardMapper, CarEtcCard> implements CarEtcCardService {
    @Autowired
    private CarInfoService carInfoService;
    @Autowired
    private CardCostInfoService cardCostInfoService;
    @Autowired
    private EtpInfoFeign etpInfoFeign;

    /**
     * 新增
     *
     * @param carEtcCard
     * @return
     */
    @Override
    public R saveInfo(CarEtcCard carEtcCard) {
        String mobile = carEtcCard.getMobile();
        Integer cardBalance = carEtcCard.getCardBalance();
        if (cardBalance == null) {
            cardBalance = 0;
        }
        if (!NumberUtil.isInteger(cardBalance.toString())) {
            return R.failed(MsgCode.INCORRECT_BALANCE.msg());
        }
        if (StrUtil.isEmpty(carEtcCard.getCardName())) {
            return R.failed("请输入卡名");
        }
        if (StrUtil.isEmpty(carEtcCard.getCardNo())) {
            return R.failed("请输入卡号");
        }
        Integer count = baseMapper.selectCount(new QueryWrapper<CarEtcCard>()
                .eq("card_no", carEtcCard.getCardNo()
                ).eq("del_flag", 0));
        if (count > 0) {
            return R.failed("该etc卡号已存在，添加失败");
        }
        Integer etpId = SecurityUtils.getUser().getEtpId();
        carEtcCard.setEtpId(etpId);
        if (this.save(carEtcCard)) {
            return R.ok("添加成功");
        }
        return R.failed("添加失败");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @Override
    public R removeByIds(String ids) {
        if (StrUtil.isBlank(ids)) {
            return R.failed(MsgCode.SELECT_NEED_DEL);
        }
        String[] split = ids.replace("\"", "").split(",");
        for (String s : split) {
            Integer id = Integer.valueOf(s);
            CarEtcCard carEtcCard = baseMapper.selectOne(new QueryWrapper<CarEtcCard>().eq("id", id));
            carEtcCard.setDelFlag(1);
            baseMapper.updateById(carEtcCard);
        }
        return R.ok("删除成功");
    }

    /**
     * 修改
     *
     * @param carEtcCard
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R updateEtcById(CarEtcCard carEtcCard) {
        log.info("要修改的etc卡信息为{}", JSONObject.toJSONString(carEtcCard));
        String mobile = carEtcCard.getMobile();
//        if (StrUtil.isEmpty(mobile)&& !Validator.isMobile(mobile)){
//            return R.failed("请输入正确的手机号码");
//        }
        if (carEtcCard.getCardBalance() == null) {
            carEtcCard.setCardBalance(0);
        }
        if (!NumberUtil.isInteger(carEtcCard.getCardBalance().toString())) {
            return R.failed(MsgCode.INCORRECT_BALANCE.msg());
        }
        if (StrUtil.isEmpty(carEtcCard.getCardName())) {
            return R.failed("请输入卡名");
        }
        if (StrUtil.isEmpty(carEtcCard.getCardNo())) {
            return R.failed("请输入卡号");
        }
        Integer id = carEtcCard.getId();
        Integer cardType = carEtcCard.getCardType();
        if (cardType == CardCostInfoConstant.CREDIT_CARD) {
            carEtcCard.setCardBalance(0);
        }
        CarEtcCard oldCarEtc = baseMapper.selectOne(new QueryWrapper<CarEtcCard>().eq("id", id)
                .eq("del_flag", 0));
        //etc卡号新旧不同
        if (!oldCarEtc.getCardNo().equals(carEtcCard.getCardNo())) {
            //判断新卡是否存在
            Integer count = baseMapper.selectCount(new QueryWrapper<CarEtcCard>().eq("card_no", carEtcCard.getCardNo())
                    .eq("del_flag", 0));
            if (count > 0) {
                return R.failed("修改的etc卡号已经存在,修改失败");
            }
        }
        this.updateById(carEtcCard);
        //信用卡不修改流水
        if (cardType == CardCostInfoConstant.CREDIT_CARD) {
            return R.ok("修改成功");
        }
        //原本余额
        Integer oldBalance = oldCarEtc.getCardBalance();
        //修改后的余额
        Integer balance = carEtcCard.getCardBalance();
        Integer margin = balance - oldBalance;
        //新增流水
        if (0 != margin) {
            CardCostInfo cardCostInfo = new CardCostInfo();
            cardCostInfo.setCardId(id);
            cardCostInfo.setCost(margin);
            cardCostInfo.setCardType(CardCostInfoConstant.ETC_CARD);
            cardCostInfo.setActionType(CardCostInfoConstant.MODIFY);
            cardCostInfo.setRemark(carEtcCard.getRemark());
            cardCostInfo.setBalance(balance);
            cardCostInfoService.saveInfo(cardCostInfo);
        }

        return R.ok("修改成功");

    }

    /**
     * 分页
     *
     * @param carFileManageReq
     * @return
     */
    @Override
    public IPage<EtcCardPageVO> queryPage(CarFileManageReq carFileManageReq) {
//        if (carFileManageReq == null) {
//            carFileManageReq = new CarFileManageReq();
//        }
        if(Objects.equals(carFileManageReq.getEtpId(),null))carFileManageReq.setEtpId(SecurityUtils.getUser().getEtpId());
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(carFileManageReq.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            carFileManageReq.setEtpIds(etpInfoSVo.getIds());
        });
       //carFileManageReq.setEtpId(SecurityUtils.getUser().getEtpId());
        return baseMapper.queryPage(carFileManageReq);
    }

    /**
     * 导出
     *
     * @param req
     */
    @Override
    public void exportExcel(CarFileManageReq req) {

        if(Objects.equals(req.getEtpId(),null))req.setEtpId(SecurityUtils.getUser().getEtpId());
        List<EtpInfoSVo> currentAndParents1 = etpInfoFeign.getCurrentAndParents1(req.getEtpId());
        currentAndParents1.forEach(etpInfoSVo -> {
            req.setEtpIds(etpInfoSVo.getIds());
        });
        req.setSize(Long.MAX_VALUE);//最多显示
        //导出数据集合
        List<Map<String, Object>> rows = new ArrayList<>();
        //需要导出的数据
        //需要导出的数据
        List<EtcCardPageVO> etcCardPageVos = baseMapper.exportExcel(req);
        if (etcCardPageVos.size() > 0) {
            for (EtcCardPageVO etcCardPageVo : etcCardPageVos) {
                LinkedHashMap<String, Object> map = new LinkedHashMap<>();
                map.put("卡名", etcCardPageVo.getCardName());
                map.put("卡号", etcCardPageVo.getCardNo());
                map.put("企业", etcCardPageVo.getEtpName());
                String cardType = etcCardPageVo.getCardType() == 0 ? "借记卡" : "信用卡";
                map.put("卡类型", cardType);
                map.put("持卡人", etcCardPageVo.getCardUser());
                map.put("持卡人手机", etcCardPageVo.getMobile());
                map.put("余额", etcCardPageVo.getCardBalance() == null ? "" : roundStr(((double) (etcCardPageVo.getCardBalance()) / 100), 2));
                map.put("绑定对象", etcCardPageVo.getBindingUser());
                map.put("备注", etcCardPageVo.getRemark());
                rows.add(map);
            }
        }
        carInfoService.carExportUtil(rows, "etc卡信息");
    }

    /**
     * etc扣费
     * 返回最新余额
     *
     * @param cardId etc卡
     * @param cost   扣费金额
     */
    @Override
    public Integer etcDeduction(Integer cardId, Integer cost) {
        CarEtcCard carEtcCard = baseMapper.selectOne(new QueryWrapper<CarEtcCard>().eq("id", cardId));
        //信用卡直接跳过
        if (carEtcCard.getCardType() == 1) {
            return 0;
        }
        //原本余额
        Integer cardBalance = carEtcCard.getCardBalance();
        carEtcCard.setCardBalance(cardBalance - cost);
        baseMapper.updateById(carEtcCard);
        return carEtcCard.getCardBalance();
    }

    /**
     * 检查是否能绑定
     *
     * @param cardId 卡id
     * @param cost   待扣费金额
     * @return
     */
    @Override
    public boolean checkIsBinding(Integer cardId, Integer cost) {
        CarEtcCard carEtcCard = baseMapper.selectOne(new QueryWrapper<CarEtcCard>().eq("id", cardId));
        //借记卡
        if (carEtcCard.getCardType() == 0) {
            Integer cardBalance = carEtcCard.getCardBalance();
            if (cardBalance == null || cost > cardBalance) {
                return false;
            }
        }
        return true;
    }

    /**
     * 费用充值
     *
     * @param req
     * @return
     */
    @Override
    public R recharge(RechargeReq req) {
        if (req == null || !NumberUtil.isInteger(req.getCost().toString()) || req.getCost() <= 0) {
            return R.failed("充值金额不合理");
        }
        Integer id = req.getId();
        Integer cost = req.getCost();
        CarEtcCard carEtcCard = baseMapper.selectOne(new QueryWrapper<CarEtcCard>().eq("id", id));
        if (carEtcCard.getCardType() == CardCostInfoConstant.CREDIT_CARD) {
            return R.failed("信用卡不可充值");
        }
        //余额
        Integer cardBalance = carEtcCard.getCardBalance();
        carEtcCard.setCardBalance(cardBalance + cost);
        baseMapper.updateById(carEtcCard);
        //新增流水
        CardCostInfo cardCostInfo = new CardCostInfo();
        cardCostInfo.setCardId(id);
        cardCostInfo.setCost(cost);
        cardCostInfo.setCardType(CardCostInfoConstant.ETC_CARD);
        cardCostInfo.setActionType(CardCostInfoConstant.RECHARGE);
        cardCostInfo.setRemark(req.getRemark());
        cardCostInfo.setCostTime(LocalDateTime.now());
        //操作后余额
        cardCostInfo.setBalance(carEtcCard.getCardBalance());
        cardCostInfoService.saveInfo(cardCostInfo);
        return R.ok("充值成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R importEtcInfo(MultipartFile file) {
        OvmsUser user = SecurityUtils.getUser();
        Integer etpId = user.getEtpId();
        List<CarEtcCard> carEtcCards = com.htstar.ovms.common.excel.util.ExcelWriter.onlyOneHeadingImport(file, CarEtcCard.class);
        int i = 1;
        ArrayList<ImportVO> error = new ArrayList<>();
        ArrayList<CarEtcCard> validated = new ArrayList<>();
        HashMap<String, Integer> licCopyMap = new HashMap<>();
        boolean allCheck = true;
        //该企业下所有车辆与绑定状态
        Map bindedLicMap = this.getCarInfoForEtcImportWithMap(etpId);
        //有效性检查
        for (CarEtcCard etcCard : carEtcCards) {
            BigDecimal bd = new BigDecimal(etcCard.getCarBalanceForDouble());
            bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal newbd = bd.multiply(new BigDecimal("100"));
            etcCard.setCardBalance(newbd.intValue());
            i++;
            int i1 = bd.intValue();
            if (etcCard.getCardName() == null || etcCard.getCardNo() == null || etcCard.getCardType() == null) {
                allCheck = false;
                ImportVO importVO = new ImportVO();
                importVO.setName("第" + i + "行有有必填项为空");
                error.add(importVO);
                continue;
            }
            Integer count = baseMapper.selectCount(new QueryWrapper<CarEtcCard>()
                    .eq("card_no", etcCard.getCardNo()
                    ).eq("del_flag", 0));
            if (count > 0) {
                allCheck = false;
                ImportVO importVO = new ImportVO();
                importVO.setName("第" + i + "行ETC卡号已存在");
                error.add(importVO);
            } else {//ETC卡未添加过

            }

            if (StringUtils.isNotBlank(etcCard.getBindCarLic())) {
                //绑定车辆检查
                String inputCarLic = etcCard.getBindCarLic();
                boolean licBinded = bindedLicMap.containsKey(etcCard.getBindCarLic());

                if (!bindedLicMap.containsKey(inputCarLic)) {
                    allCheck = false;
                    ImportVO importVO = new ImportVO();
                    importVO.setName("第" + i + "行中的车牌不存在该企业");
                    error.add(importVO);
                } else {//企业中有该车牌
                    Map licMap = (Map) bindedLicMap.get(inputCarLic);
                    Long binded = (Long) licMap.get("binded");
                    if (binded == 1) {//已绑定过etc
                        allCheck = false;
                        ImportVO importVO = new ImportVO();
                        importVO.setName("第" + i + "行中的车牌已绑定etc");
                        error.add(importVO);
                    } else {//
                        Integer carId = (Integer) licMap.get("id");
                        etcCard.setBindingId(carId);//绑定车辆
                    }
                }
            }
            //存入车牌map并检查excel中重复
            boolean licExc = licCopyMap.containsKey(etcCard.getBindCarLic());
            if(!Objects.equals(null,etcCard.getBindCarLic())&& !etcCard.getBindCarLic().equals("")) {
                if (licExc) {
                    allCheck = false;
                    ImportVO importVO = new ImportVO();
                    importVO.setName("第" + i + "行的车牌与第" + licCopyMap.get(etcCard.getBindCarLic()) + "重复");
                    error.add(importVO);
//                continue;
                }
            }
            //存一个车牌map于用检查重复
            if (licExc == false) {
                licCopyMap.put(etcCard.getBindCarLic(), i);
            }
            if (allCheck == true) {
                etcCard.setEtpId(etpId);
                validated.add(etcCard);  //改为检验全部合法才保存
            }
        }
        if (allCheck) {
            this.saveBatch(validated);
            return R.ok().setMsg("保存成功");
        }
        //返回有误信息
        DeviceImportVO vo = new DeviceImportVO();
        vo.setError(error);
        return R.ok(vo).setMsg("模板有数据有误，请进行更改再导入").setCode(2);
    }

    @Override
    public List<String> getCarInfoForEtcImport(int i) {
        List<String> rs = baseMapper.getCarInfoForEtcImport(i);
        return rs;
    }

    public Map getCarInfoForEtcImportWithMap(Integer i) {
        Map rs = baseMapper.getCarInfoForEtcImportWithMap(i);
        return rs;
        /**
         * Consume( hash(@1), hash(new x in x!([1, 2]) ...) )
         */
    }

    private ConcurrentHashMap<String, List<CarInfo>> validateForEtcinfo(CarInfo carInfo) {
        Boolean flag = true;
        return null;
    }
}
